﻿using IdentityModel;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ConfigurationDbContext = Devonline.Identity.Admin.Models.ConfigurationDbContext;

namespace Devonline.Identity.Admin.Controllers;

/// <summary>
/// 接口管理
/// </summary>
[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class ApisController(
    AdminSetting appSetting,
    ConfigurationDbContext configurationDbContext,
    PersistedGrantDbContext persistedGrantDbContext,
    IFileService fileService,
    ILogger<ApisController> logger) : ControllerBase
{
    private readonly AdminSetting _appSetting = appSetting;
    private readonly ConfigurationDbContext _configurationDbContext = configurationDbContext;
    private readonly PersistedGrantDbContext _persistedGrantDbContext = persistedGrantDbContext;
    private readonly IFileService _fileService = fileService;
    private readonly ILogger<ApisController> _logger = logger;

    [AllowAnonymous, HttpGet("init")]
    public async Task<IActionResult> InitIdentityDataAsync()
    {
        await _configurationDbContext.AutoMigrationAsync();
        await _persistedGrantDbContext.AutoMigrationAsync();
        _logger.LogInformation("数据迁移完成!");

        string fileName = Request.GetRequestOption<string>(nameof(fileName)) ?? "identityData.json";
        if (!System.IO.File.Exists(fileName))
        {
            fileName = _fileService.GetAttachmentPath(fileName);
        }

        if (!System.IO.File.Exists(fileName))
        {
            return BadRequest("认证数据配置文件不存在!");
        }

        var json = System.IO.File.ReadAllText(fileName);
        if (string.IsNullOrWhiteSpace(json))
        {
            return BadRequest("认证数据配置文件内容为空!");
        }

        var identityData = json.ToJsonObject<IdentityData>();
        ArgumentNullException.ThrowIfNull(identityData);

        #region IdentityResource
        //追加模式开关
        bool add = Request.GetRequestOption<bool>(nameof(add));
        if (!add)
        {
            var identityResources = await _configurationDbContext.IdentityResources.ToListAsync();
            if (identityResources.IsNotNullOrEmpty())
            {
                _configurationDbContext.IdentityResources.RemoveRange(identityResources);
            }
        }

        foreach (var resource in identityData.IdentityResources)
        {
            await _configurationDbContext.IdentityResources.AddAsync(resource.ToEntity());
        }
        #endregion

        #region ApiScope
        if (!add)
        {
            var apiScopes = await _configurationDbContext.ApiScopes.ToListAsync();
            if (apiScopes.IsNotNullOrEmpty())
            {
                _configurationDbContext.ApiScopes.RemoveRange(apiScopes);
            }
        }

        foreach (var apiScope in identityData.ApiScopes)
        {
            await _configurationDbContext.ApiScopes.AddAsync(apiScope.ToEntity());
        }
        #endregion

        #region ApiResource
        if (!add)
        {
            var apiResources = await _configurationDbContext.ApiResources.ToListAsync();
            if (apiResources.IsNotNullOrEmpty())
            {
                _configurationDbContext.ApiResources.RemoveRange(apiResources);
            }
        }

        ArgumentNullException.ThrowIfNull(_appSetting.DefaultPassword);
        foreach (var resource in identityData.ApiResources)
        {
            resource.ApiSecrets.Add(new IdentityServer4.Models.Secret(_appSetting.DefaultPassword.ToSha256()));
            await _configurationDbContext.ApiResources.AddAsync(resource.ToEntity());
        }
        #endregion

        #region Client
        if (!add)
        {
            var clients = await _configurationDbContext.Clients.ToListAsync();
            if (clients.IsNotNullOrEmpty())
            {
                _configurationDbContext.Clients.RemoveRange(clients);
            }
        }

        foreach (var client in identityData.Clients)
        {
            client.ClientSecrets.Add(new IdentityServer4.Models.Secret(_appSetting.DefaultPassword.ToSha256()));
            //client.Claims = client.Claims.Select(c => new ClientClaim(c.Type, c.Value)).ToList();
            await _configurationDbContext.Clients.AddAsync(client.ToEntity());
        }
        #endregion

        await _configurationDbContext.SaveChangesAsync();
        _logger.LogInformation("认证数据导入完成!");
        return Ok();
    }
}